﻿using MaterialDesignThemes.Wpf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using UIWindows.Attributes;

namespace UIWindows.UserControls
{
    /// <summary>
    /// ParameterContainerControls.xaml 的交互逻辑
    /// </summary>
    public partial class ParameterContainerControls : UserControl
    {
        private bool isInput = false;
        public ParameterContainerControls()
        {
            InitializeComponent();
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            if (isInput)
            {
                return;
            }
            isInput = true;
            object parameter = DataContext;
            var property = parameter.GetType().GetProperties();
            for (int i = 0; i < property.Length;)
            {
                var attr = property[i].GetCustomAttribute<UIMarkAttribute>();
                if (attr == null) { i++; continue; }
                MyStackPanel.Children.Add(CreatePanel(property, ref i, property.Length, attr.LayerNumber));
            }
        }

        private Grid CreatePanel(PropertyInfo[] properties, ref int index, int indexMax, int layer)
        {
            Grid grid = new Grid();
            grid.Height = 40;
            ColumnDefinitionCollection columns = grid.ColumnDefinitions;
            int width = layer < 3 ? 100 : 50;
            for (int i = 0; i < layer; i++)
            {
                columns.Add(new ColumnDefinition()
                {
                    Width = new GridLength((layer == 3) && (i == 0) ? 80 : width),
                });
                columns.Add(new ColumnDefinition()
                {
                    Width = new GridLength(layer == 1 ? 300 : layer == 3 ? 80 : 100),
                });
            }
            return CreateContent(properties, 0, ref index, grid, indexMax, width, layer == 1 ? 300 : layer == 3 ? 80 : 100, layer);
        }

        private Grid CreateContent(PropertyInfo[] properties, int column, ref int index, Grid grid, int indexMax, int blockWidth, int width, int layer)
        {
            if (layer == 0 || index >= indexMax) { return grid; }
            var attribute = properties[index].GetCustomAttribute<UIMarkAttribute>();
            if (attribute != null) 
            {
                grid.Children.Add(GetTextBlock(attribute, column * 2, blockWidth));
                grid.Children.Add(GetContent(attribute, properties[index], column * 2 + 1, width));
                layer -= 1;
                column++;
            }
            index++;
            return CreateContent(properties, column, ref index, grid, indexMax, blockWidth, width, layer);

        }

        private FrameworkElement GetContent(UIMarkAttribute attribute, PropertyInfo propertyInfo, int column, int width)
        {
            if (propertyInfo.PropertyType.BaseType.Name == "Enum")
            {
                return GetComboBox(propertyInfo.Name, column, attribute.CollectionName, attribute.MyExpression);
            }
            switch (propertyInfo.PropertyType.Name)
            {
                case "Double":
                case "Int32":
                case "UInt32":
                    return GetTextBox(propertyInfo.Name, attribute.Suffix, column);
            }
            return default;
        }

        private TextBlock GetTextBlock(UIMarkAttribute attribute, int column, int width)
        {
            TextBlock textBlock = new TextBlock();
            textBlock.Text = attribute.Name;
            textBlock.HorizontalAlignment = HorizontalAlignment.Right;
            textBlock.VerticalAlignment = VerticalAlignment.Center;
            textBlock.SetValue(Grid.ColumnProperty, column);
            return textBlock;
        }

        private TextBox GetTextBox(string bingd, string suffix, int column)
        {
            TextBox textBox = new TextBox();
            textBox.VerticalAlignment = VerticalAlignment.Center;
            textBox.Margin = new Thickness(5);
            textBox.SetValue(Grid.ColumnProperty, column);
            textBox.SetValue(TextFieldAssist.SuffixTextProperty, suffix);
            Binding binding = new Binding();
            binding.Source = DataContext;
            binding.Path = new PropertyPath(bingd);
            binding.Mode = BindingMode.TwoWay;
            binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
            BindingOperations.SetBinding(textBox, TextBox.TextProperty, binding);
            return textBox;
        }

        private ComboBox GetComboBox(string bingd, int column, Type type, string[] expression)
        {
            ComboBox comboBox = new ComboBox();
            comboBox.SetValue(Grid.ColumnProperty, column);
            if (expression != null)
            {
                System.Linq.Expressions.Expression<Func<string, bool>> condition = x => !x.Contains(expression[0]);
                for (int i = 1; i < expression.Length; i++)
                {
                    string str = expression[i];
                    System.Linq.Expressions.Expression<Func<string, bool>> classExp = s => s != str;
                    var invokedExpr = System.Linq.Expressions.Expression.Invoke(classExp, condition.Parameters.Cast<System.Linq.Expressions.Expression>());
                    condition = System.Linq.Expressions.Expression.Lambda<Func<string, bool>>(System.Linq.Expressions.Expression.AndAlso(condition.Body, invokedExpr), condition.Parameters);
                }
                comboBox.ItemsSource = type.GetEnumNames().Where(condition.Compile());
            }
            else
            {
                comboBox.ItemsSource = type.GetEnumNames();
            }
            comboBox.VerticalAlignment = VerticalAlignment.Center;
            comboBox.Width = 90;
            comboBox.Margin = new Thickness(5);
            Binding binding = new Binding();
            binding.Source = DataContext;
            binding.Path = new PropertyPath(bingd);
            binding.Mode = BindingMode.TwoWay;
            binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
            BindingOperations.SetBinding(comboBox, ComboBox.TextProperty, binding);
            return comboBox;
        }

    }
}
